<!--- CacheManager.cfc --->

<!---
	* Date:26/1/2010 09:49:26 
	* Author: Cristian Costantini 
	* Version: 1.0.0 beta 2
	* License: http://www.apache.org/licenses/LICENSE-2.0
	* File: CacheManager.cfc 
	 --->

<!--- 
	Release Notes API
	* from removeAll to removeCache
	* from removeCache to removeElement
	 --->

<cfcomponent output="false" name="CacheManager">
	
    <!--- constructor --->
    
    <cffunction name="init" access="public" returntype="cacheManagement.CacheManager" output="false">
        <cfargument name="config" type="String" required="true" hint="absolute path Xml config cache" />
        <cfargument name="rootLib" type="String" required="false" default="/cacheManagement/lib/" hint="Root of ehcache jar library" />
		<cfargument name="loadLib" type="boolean" required="false" default="true" hint="If true create ehcache object with javaLoader or use class on java root." />
        <cfscript>
        var file = createObject( 'java', 'java.io.FileInputStream' ).init(  arguments.config );
        
        setFactory( createObject( 'component', 'cacheManagement.factory.CacheFactory' ).init( arguments.rootLib, arguments.loadLib ) );
        
        setCacheManager( getFactory().createCacheManager().init( file ) );
        
        setEventManager( getFactory().createEventManager() );
        
        </cfscript>
        <cfreturn this />
    </cffunction>
    
    <!--- public --->

	<cffunction name="getVersion" access="public" returntype="String">
		<cfreturn "1.0.0 - Alpha 1">
	</cffunction>
	
	<cffunction name="createCache" access="public" returntype="Any" output="false" hint="Create a cache object">
        <cfargument name="class" type="String" required="true" />
        <cfargument name="maxElementsInMemory" type="Numeric" required="false" default="1000"/>
        <cfargument name="overflowToDisk" type="boolean" required="false" default="false" />
		<cfargument name="eternal" type="boolean" required="false" default="false" />
		<cfargument name="timeToLiveSeconds" type="Numeric" required="false" default="120" />
		<cfargument name="timeToIdleSeconds" type="Numeric" required="false" default="120" />
		<cfargument name="diskPersistent" type="boolean" required="false" default="false" />
		<cfargument name="diskExpiryThreadIntervalSeconds" type="Numeric" required="false" default="1" />
        <cfscript>
        var cache = getFactory().createCache().init(	arguments.class, arguments.maxElementsInMemory, 
        												arguments.overflowToDisk, arguments.eternal, arguments.timeToLiveSeconds, 
        												arguments.timeToIdleSeconds, arguments.diskPersistent, 
        												arguments.diskExpiryThreadIntervalSeconds );
        
        return cache;
        </cfscript>
    </cffunction>
	
	<cffunction name="createElement" access="public" returntype="Any" output="false" hint="Create a cache element object">
        <cfargument name="key" type="String" required="true" />
        <cfargument name="value" type="Any" required="true" />
		<cfargument name="eternal" type="boolean" required="false" default="false" />
		<cfargument name="timeToIdleSeconds" type="Numeric" required="false" default="10" />
		<cfargument name="timeToLiveSeconds" type="Numeric" required="false" default="10" />
        <cfscript>
        var element = getFactory().createElement().init(	arguments.key, arguments.value, 
        													arguments.eternal, arguments.timeToIdleSeconds, arguments.timeToLiveSeconds );
        
        return element;
        </cfscript>
    </cffunction>
	
	<cffunction name="addCache" access="public" returntype="void" output="false" hint="Add a cache to the cacheManager">
		<cfargument name="cache" type="Any" required="true" hint="net.sf.ehcache.Cache" />
		<cfscript>
		getCacheManager().addCache( arguments.cache );
		
		getCacheEventNotificationService().notifyCacheAdded( arguments.cache );
		</cfscript>
	</cffunction>
	
	<cffunction name="put" access="public" returntype="void" output="false" hint="Add an Element to the cache">
		<cfargument name="class" type="String" required="true" />
		<cfargument name="element" type="Any" required="true" hint="net.sf.ehcache.Element" />
		<cfscript>
		var cache = getCacheManager().getCache( arguments.class );
		
		cache.put( arguments.element );
		
		getCacheEventNotificationService().notifyElementPut( arguments.element );
		</cfscript>
	</cffunction>

	<cffunction name="removeCache" access="public" returntype="void" output="false" hint="Remove a cache object">
        <cfargument name="class" type="String" required="true" />
        <cfscript>
        getCacheManager().removeCache( arguments.class );
        
        getCacheEventNotificationService().notifyCacheRemoved( arguments.class );
        </cfscript>
    </cffunction>

	<!--- event management --->
	
	<cffunction name="registerListener" access="public" returntype="void" output="false" hint="Add an event listener to cache object">
		<cfargument name="name" type="String" required="true" />
		<cfargument name="listener" type="Any" required="true" />
		<cfargument name="async" type="boolean" required="false" default="false">
		<cfscript>
		getCacheEventNotificationService().registerListener( arguments.name, arguments.listener, arguments.async );
		
		</cfscript>
	</cffunction>
	
	<cffunction name="unregisterListener" access="public" returntype="void" output="false" hint="Remove an event listener to cache object">
		<cfargument name="name" type="String" required="true" />
		<cfargument name="listener" type="Component" required="true" />
		<cfscript>
		getCacheEventNotificationService().unregisterListener( arguments.name, arguments.listener );
		
		</cfscript>
	</cffunction>
	
	<cffunction name="getCacheEventNotificationService" access="private" returntype="Any" output="false" hint="">
		<cfscript>
		return getEventManager();
		</cfscript>
	</cffunction>

	<cffunction name="getEhCacheEventNotificationService" access="public" returntype="Any" output="false" hint="Manage EhCache eventListener. Return net.sf.ehcache.event.RegisteredEventListeners">
		<cfargument name="class" type="String" required="true" />
		<cfscript>
		var cache = getCacheManager().getCache( arguments.class );
		var nService = cache.getCacheEventNotificationService();
		
		return nService;
		</cfscript>
	</cffunction>
	
	<!---  --->
    
    <cffunction name="add" access="public" returntype="void" output="false" hint="Add an element to the cache from Xml configuration or default value.">
        <cfargument name="class" type="String" required="true" />
        <cfargument name="key" type="String" required="true" />
        <cfargument name="value" type="Any" required="true" />
        <cfscript>
        var cache = "";
        var element = getFactory().createElement().init( arguments.key, arguments.value );
        
        if( getCacheManager().cacheExists( arguments.class ) ){
        
        	put( arguments.class, element );
        
        }else{
        
        	getCacheManager().addCache( arguments.class );
        	
        	put( arguments.class, element );
        
        }
        </cfscript>
    </cffunction>
    
    <cffunction name="removeAll" access="public" returntype="void" output="false" hint="remove all elements into the cache">
        <cfargument name="class" type="String" required="true" />
        <cfscript>
        getCacheManager().getCache( arguments.class ).removeAll();
        
        getCacheEventNotificationService().notifyRemoveAll();
        </cfscript>
    </cffunction>

    <cffunction name="removeElement" access="public" returntype="boolean" output="false" hint="remove a element of the cache">
        <cfargument name="class" type="String" required="true" />
        <cfargument name="key" type="String" required="true" />
        <cfscript>
        var cache = "";
        var result = false;
        
       	cache = getCacheManager().getCache( arguments.class );
        
        result = cache.remove( arguments.key );
        
        getCacheEventNotificationService().notifyElementRemoved( arguments.key );
        
        return result;
        </cfscript>
    </cffunction>
    
    <cffunction name="exists" access="public" returntype="boolean" output="false" hint="Return a boolean. Check the key exists into the cache">
        <cfargument name="class" type="String" required="true" />
        <cfargument name="key" type="String" required="true" />
        <cfscript>
        var cache = "";
        var element = "";
        var result = false;
        
        if( cacheExists( arguments.class ) ){
        
        	cache = getCacheManager().getCache( arguments.class );
        	
        	if( cache.isKeyInCache( arguments.key ) ){
        		
        		if( not isExpired( arguments.class, arguments.key ) ){
        		
        			result = true;
        		
        		}
        		
        	}
        		
        }
        
        return result;
        </cfscript>
    </cffunction>
    
    <cffunction name="cacheExists" access="public" returntype="boolean" output="false" hint="Check a cache">
        <cfargument name="class" type="String" required="true" />
        <cfscript>
        return getCacheManager().cacheExists( arguments.class );
        </cfscript>
    </cffunction>
    
    <cffunction name="get" access="public" returntype="Any" output="false" hint="get value cache">
        <cfargument name="class" type="String" required="true" />
        <cfargument name="key" type="String" required="true" />
        <cfscript>
        var cache = "";
        var result = false;
        
       	cache = getCacheManager().getCache( arguments.class );
        
        result = cache.get( arguments.key ).getObjectValue();
        
        return result;
        </cfscript>
    </cffunction>
    
    <cffunction name="flush" access="public" returntype="void" output="false" hint="Flush a cache">
        <cfargument name="class" type="String" required="true" />
        <cfscript>
       	getCacheManager().getCache( arguments.class ).flush();
        </cfscript>
    </cffunction>
    
    <cffunction name="getCacheNames" access="public" returntype="Array" output="false" hint="get cache items">
        <cfscript>
        return getCacheManager().getCacheNames();
        </cfscript>
    </cffunction>
	
	<!--- Added from Dave DeVol --->
	<cffunction name="getCacheKeys" access="public" returntype="Array" output="false" hint="get all keys for a cache.">
		<cfargument name="class" type="String" required="true" />
		<cfscript>
		var cache = "";
		var result = arrayNew(1);
		
		if(getCacheManager().cacheExists( arguments.class )){
		
			cache = getCacheManager().getCache( arguments.class );
		
			result = cache.getKeys();
		
		}
		
		return result;
		</cfscript>
	</cffunction>
    
    <cffunction name="getDiskStorePath" access="public" returntype="String" output="false" hint="return path of cache in the disk store ">
        <cfreturn getCacheManager().getDiskStorePath() />
    </cffunction>

    <!--- statistics --->
    
    <cffunction name="clearStatistics" access="public" returntype="void" output="false" hint="Reset statistics set counter to 0">
        <cfargument name="class" type="String" required="true" />
        <cfscript>
       	getCacheManager().getCache( arguments.class ).clearStatistics();
        </cfscript>
    </cffunction>
    
    <cffunction name="getStatistics" access="public" returntype="cacheManagement.Statistics" output="false">
        <cfargument name="class" type="String" required="true" />
        <cfreturn getFactory().createCacheStatistics( getCacheManager().getCache( arguments.class ) ) />
    </cffunction>
	
	<!--- private --->

    <cffunction name="isExpired" access="private" returntype="boolean" output="false">
        <cfargument name="class" type="String" required="true" />
        <cfargument name="key" type="String" required="true" />
        <cfscript>
        var result = false;
        var element = "";
        
       	element = getCacheManager().getCache( arguments.class ).get( arguments.key );
       	
       	if( isDefined( 'element' ) ){
       	
       		result = element.isExpired();
       	
       	}else{
       	
       		result = true;
       	
       	}
       	
       	
       	if( result ){
       	
       		getCacheEventNotificationService().notifyElementExpiry( arguments.key );
       		
       	}
       	
        return result;
        </cfscript>
    </cffunction>
	
    <cffunction name="setFactory" access="private" returntype="void" output="false">
        <cfargument name="factory" type="cacheManagement.factory.CacheFactory" required="true" />
        <cfset variables.factory = arguments.factory />
    </cffunction>
    
    <cffunction name="getFactory" access="private" returntype="cacheManagement.factory.CacheFactory" output="false">
        <cfreturn variables.factory />
    </cffunction>
    
    <cffunction name="setCacheManager" access="private" returntype="void" output="false">
        <cfargument name="cacheManager" type="Any" required="true" />
		
		<cfset variables.cacheManager = arguments.cacheManager />
    </cffunction>
    
    <cffunction name="getCacheManager" access="private" returntype="Any" output="false">
        <cfreturn variables.cacheManager />
    </cffunction>
    
    <cffunction name="setEventManager" access="private" returntype="void" output="false">
        <cfargument name="EventManager" type="Any" required="true" />
		
		<cfset variables.EventManager = arguments.EventManager />
    </cffunction>
    
    <cffunction name="getEventManager" access="private" returntype="Any" output="false">
        <cfreturn variables.EventManager />
    </cffunction>
	
</cfcomponent>